GtkDirectionType direction);
static gboolean gtk_widget_real_keynav_failed (GtkWidget *widget,
GtkDirectionType direction);
+static void gtk_widget_root (GtkWidget *widget);
+static void gtk_widget_unroot (GtkWidget *widget);
#ifdef G_ENABLE_CONSISTENCY_CHECKS
static void gtk_widget_verify_invariants (GtkWidget *widget);
static void gtk_widget_push_verify_invariants (GtkWidget *widget);
}
}
+static void
+gtk_widget_real_root (GtkWidget *widget)
+{
+ gtk_widget_forall (widget, (GtkCallback) gtk_widget_root, NULL);
+}
+
+static void
+gtk_widget_real_unroot (GtkWidget *widget)
+{
+ gtk_widget_forall (widget, (GtkCallback) gtk_widget_unroot, NULL);
+}
+
static void
gtk_widget_class_init (GtkWidgetClass *klass)
{
klass->unmap = gtk_widget_real_unmap;
klass->realize = gtk_widget_real_realize;
klass->unrealize = gtk_widget_real_unrealize;
+ klass->root = gtk_widget_real_root;
+ klass->unroot = gtk_widget_real_unroot;
klass->size_allocate = gtk_widget_real_size_allocate;
klass->get_request_mode = gtk_widget_real_get_request_mode;
klass->measure = gtk_widget_real_measure;
gtk_css_node_set_visible (priv->cssnode, priv->visible);
/* need to set correct type here, and only class has the correct type here */
gtk_css_node_set_widget_type (priv->cssnode, G_TYPE_FROM_CLASS (g_class));
+
+ if (g_type_is_a (G_TYPE_FROM_CLASS (g_class), GTK_TYPE_ROOT))
+ priv->root = (GtkRoot *) widget;
}
return widget;
}
+static void
+gtk_widget_root (GtkWidget *widget)
+{
+ GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+
+ /* roots are rooted by default */
+ if (GTK_IS_ROOT (widget))
+ return;
+
+ g_assert (priv->root == NULL);
+ g_assert (!priv->realized);
+ g_assert (priv->parent);
+ g_assert (priv->parent->priv->root);
+
+ priv->root = priv->parent->priv->root;
+
+ GTK_WIDGET_GET_CLASS (widget)->root (widget);
+}
+
+static void
+gtk_widget_unroot (GtkWidget *widget)
+{
+ GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
+
+ /* roots are rooted by default and cannot be unrooted */
+ if (GTK_IS_ROOT (widget))
+ return;
+
+ g_assert (priv->root);
+ g_assert (!priv->realized);
+
+ GTK_WIDGET_GET_CLASS (widget)->unroot (widget);
+
+ priv->root = NULL;
+}
+
/**
* gtk_widget_unparent:
* @widget: a #GtkWidget
if (_gtk_widget_get_realized (widget))
gtk_widget_unrealize (widget);
+ if (priv->root)
+ gtk_widget_unroot (widget);
+
/* If we are unanchoring the child, we save around the toplevel
* to emit hierarchy changed
*/
gtk_list_list_model_item_removed (old_parent->priv->children_observer, old_prev_sibling);
if (toplevel)
- {
- _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
- g_object_unref (toplevel);
- }
+ _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
+
+ g_clear_object (&toplevel);
/* Now that the parent pointer is nullified and the hierarchy-changed
* already passed, go ahead and unset the parent window, if we are unparenting
}
if (priv->parent->priv->anchored && prev_parent == NULL)
- _gtk_widget_propagate_hierarchy_changed (widget, NULL);
+ {
+ _gtk_widget_propagate_hierarchy_changed (widget, NULL);
+ }
+ if (parent->priv->root && priv->root == NULL)
+ gtk_widget_root (widget);
if (prev_parent == NULL)
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_PARENT]);
* widget is destroyed, which means that gtk_widget_unrealize() has
* been called or the widget has been unmapped (that is, it is going
* to be hidden).
+ * @root: Called when the widget gets added to a #GtkRoot widget.
+ * @unroot: Called when the widget is about to be removed from its
+ * #GtkRoot widget.
* @size_allocate: Signal emitted to get the widget allocation.
* @state_flags_changed: Signal emitted when the widget state changes,
* see gtk_widget_get_state_flags().
void (* unmap) (GtkWidget *widget);
void (* realize) (GtkWidget *widget);
void (* unrealize) (GtkWidget *widget);
+ void (* root) (GtkWidget *widget);
+ void (* unroot) (GtkWidget *widget);
void (* size_allocate) (GtkWidget *widget,
int width,
int height,